package torres.entity;

import java.util.*;

import torres.fileIO.BasicContainer;
import torres.ability.Ability;
import torres.ability.AbilityManager;
import torres.action.Effect;
import torres.fileIO.ClassContainer;
import torres.item.WeaponType;
import torres.map.Location;
import torres.map.World;


/**
 * @author Torres
 * A specific Occupation that specializes in disabling and avoiding
 * traps. The primary stat of a Sneak is Agility.
 */

public class Sneak implements Occupation {
	private LinkedHashSet<Ability> sneakAbilityList;
	private LinkedHashSet<Ability> sneakAttackList;
	private final Stat sneakPrimaryStat = Stat.AGILITY;
	private final Job job = Job.SNEAK;
	private double sneakStrengthMultiplier;
	private double sneakAgilityMultiplier;
	private double sneakIntellectMultiplier;
	private int pickPocketSkill;
	private int detectRemoveTrapSkill;
	private int creepSkill;
	private int rangedWeaponSkill;
	private final String name = "Sneak";
	
	/**
	 * Creates a default Sneak
	 */
	public Sneak() { // Default Constructor
		sneakAbilityList = new LinkedHashSet<Ability>(3);
		sneakAttackList = new LinkedHashSet<Ability>(3);
		sneakStrengthMultiplier = 1.15;
		sneakAgilityMultiplier = 1.3;
		sneakIntellectMultiplier = 1.15;
		pickPocketSkill = 0;
		detectRemoveTrapSkill = 0;
		creepSkill = 0;
		rangedWeaponSkill = 0;
	}
	
	/**
	 * Creates a new Sneak with the specified values. 
	 * @param abilityList The ability list.
	 * @param strength The strength multiplier.
	 * @param agility The agility multiplier.
	 * @param intellect The intellect multiplier.
	 */
	public Sneak(LinkedHashSet<Ability> abilityList, double strength, double agility, double intellect) {
		this.sneakAbilityList = abilityList;
		this.sneakStrengthMultiplier = strength;
		this.sneakAgilityMultiplier = agility;
		this.sneakIntellectMultiplier = intellect;
		sneakAbilityList = new LinkedHashSet<Ability>(3);
		sneakAttackList = new LinkedHashSet<Ability>(3);
	}

	/* (non-Javadoc)
	 * @see torres.entity.Occupation#getAgilityMultiplier()
	 */
	public double getAgilityMultiplier() {
		return sneakAgilityMultiplier;
	}

	/* (non-Javadoc)
	 * @see torres.entity.Occupation#getIntellectMultiplier()
	 */
	public double getIntellectMultiplier() {
		return sneakIntellectMultiplier;
	}

	/* (non-Javadoc)
	 * @see torres.entity.Occupation#getPrimarySkill()
	 */
	public Stat getPrimaryStat() {
		return sneakPrimaryStat;
	}

	/* (non-Javadoc)
	 * @see torres.entity.Occupation#getStrengthMultiplier()
	 */
	public double getStrengthMultiplier() {
		return sneakStrengthMultiplier;
	}

	/* (non-Javadoc)
	 * @see torres.entity.Occupation#getAbilityList()
	 */
	public LinkedHashSet<Ability> getAbilityList() {
		return sneakAbilityList;
	}
	
	/* (non-Javadoc)
	 * @see torres.entity.Occupation#getJob()
	 */
	public Job getJob() {
		return job;
	}
	
	/**
	 * Sets detectRemoveTrapSkill level of Sneak.
	 * @param detectRemoveTrapSkill the new detectRemoveTrapSkill value to set
	 */
	public void setDetectRemoveTrapSkill(int detectRemoveTrapSkill) {
		this.detectRemoveTrapSkill = detectRemoveTrapSkill;
	}

	/**
	 * Returns detectRemoveTrapSkill.
	 * @return the detectRemoveTrapSkill
	 */
	public int getDetectRemoveTrapSkill() {
		return detectRemoveTrapSkill;
	}

	/**
	 * Sets creepSkill level of Sneak.
	 * @param creepSkill the new creepSkill value to set
	 */
	public void setCreepSkill(int creepSkill) {
		this.creepSkill = creepSkill;
	}

	/**
	 * Returns creepSkill
	 * @return the creepSkill
	 */
	public int getCreepSkill() {
		return creepSkill;
	}

	/**
	 * Sets rangedWeaponSkill of Sneak.
	 * @param rangedWeaponSkill the new rangedWeaponSkill value to set
	 */
	public void setRangedWeaponSkill(int rangedWeaponSkill) {
		this.rangedWeaponSkill = rangedWeaponSkill;
	}

	/**
	 * Returns rangedWeaponSkill
	 * @return the rangedWeaponSkill
	 */
	public int getRangedWeaponSkill() {
		return rangedWeaponSkill;
	}
	
	/**
	 * Sets pickPocketSkill level of Sneak.
	 * @param pickPocketSkill the new pickPocketSkill value to set
	 */
	public void setPickPocketSkill(int pickPocketSkill) {
		this.pickPocketSkill = pickPocketSkill;
	}

	/**
	 * Returns pickPocketSkill
	 * @return the pickPocketSkill
	 */
	public int getPickPocketSkill() {
		return pickPocketSkill;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		return name;
	}

	/* (non-Javadoc)
	 * @see torres.fileIO.Saveable#save()
	 */
	@Override
	public ClassContainer save() {
		ClassContainer curClass = new ClassContainer("Job");
		//ClassContainer curStructure = new ClassContainer("AbilityList");
		/*
		for(Ability ability: sneakAbilityList) {
			curStructure.addProperty(ability.save());
		}
		*/
		//curClass.addProperty(curStructure);
		curClass.addProperty(new BasicContainer("sneakStrengthMultiplier", sneakStrengthMultiplier));
		curClass.addProperty(new BasicContainer("sneakAgilityMultiplier", sneakAgilityMultiplier));
		curClass.addProperty(new BasicContainer("sneakIntellectMultiplier", sneakIntellectMultiplier));
		curClass.addProperty(new BasicContainer("pickPocketSkill", pickPocketSkill));
		curClass.addProperty(new BasicContainer("detectRemoveTrapSkill", detectRemoveTrapSkill));
		curClass.addProperty(new BasicContainer("creepSkill", creepSkill));
		curClass.addProperty(new BasicContainer("rangedWeaponSkill", rangedWeaponSkill));
		
		return curClass;
	}

	/* (non-Javadoc)
	 * @see torres.fileIO.Saveable#load(torres.fileIO.ClassContainer)
	 */
	@Override
	public void load(ClassContainer classContainer) {
		BasicContainer sneakStrengthMultiplierCont = (BasicContainer)classContainer.getProperty("sneakStrengthMultiplier");
		sneakStrengthMultiplier = Double.parseDouble((String)sneakStrengthMultiplierCont.getValue());
		BasicContainer sneakAgilityMultiplierCont = (BasicContainer)classContainer.getProperty("sneakAgilityMultiplier");
		sneakAgilityMultiplier = Double.parseDouble((String)sneakAgilityMultiplierCont.getValue());
		BasicContainer sneakIntellectMultiplierCont = (BasicContainer)classContainer.getProperty("sneakIntellectMultiplier");
		sneakIntellectMultiplier = Double.parseDouble((String)sneakIntellectMultiplierCont.getValue());
		BasicContainer pickPocketSkillCont = (BasicContainer)classContainer.getProperty("pickPocketSkill");
		pickPocketSkill = Integer.parseInt((String)pickPocketSkillCont.getValue());
		BasicContainer detectRemoveTrapSkillCont = (BasicContainer)classContainer.getProperty("detectRemoveTrapSkill");
		detectRemoveTrapSkill = Integer.parseInt((String)detectRemoveTrapSkillCont.getValue());
		BasicContainer creepSkillCont = (BasicContainer)classContainer.getProperty("creepSkill");
		creepSkill = Integer.parseInt((String)creepSkillCont.getValue());
		BasicContainer rangedWeaponSkillCont = (BasicContainer)classContainer.getProperty("rangedWeaponSkill");
		rangedWeaponSkill = Integer.parseInt((String)rangedWeaponSkillCont.getValue());
		
	}
	
	/* (non-Javadoc)
	 * @see torres.entity.Occupation#updateAbilityList(int)
	 */
	@Override
	public void updateAbilityList(int level) {
		// TODO Auto-generated method stub
		AbilityManager.getInstance().updateAbilityList(sneakAbilityList, level, this.getJob());
		
	}
	@Override
	public boolean allocateSkillPoint(Skill skill) {
		// TODO Auto-generated method stub
		switch(skill) {	
			case PICKPOCKET : 
				if (pickPocketSkill < 35) 
					pickPocketSkill++; 
				else 
					return false;
				break;
			case DETECT_REMOVE_TRAP : 
				if (detectRemoveTrapSkill<35) 
					detectRemoveTrapSkill++;
				else 
					return false;
				break;
			case CREEP : 
				if (creepSkill<35) 
					creepSkill++; 
				else 
					return false;
				break;
			case RANGEDWEAPON : 
				if(rangedWeaponSkill<35) 
					rangedWeaponSkill++; 
				else 
					return false;
				break;
			default : 
				System.err.println("Sneak.allocateSkillPoint(): " +
						"Skill point was not allocated. Skill: " + skill.toString());
				return false;
		}
		return true;
	}
	public LinkedHashSet<String> retreiveSkillList(LinkedHashSet<String> skillList) {
		skillList.add("Pick-pocket Skill:\t\t\t" + this.pickPocketSkill);
		skillList.add("Detect/Remove Trap Skill:\t\t\t" + this.detectRemoveTrapSkill);
		skillList.add("Creep Skill:\t\t\t" + this.creepSkill);
		skillList.add("Ranged Weapon Skill:\t\t\t" + this.rangedWeaponSkill);
		return skillList;
	}

	@Override
	public LinkedHashSet<Skill> retreiveSkillEnumList(LinkedHashSet<Skill> hashSet) {
		hashSet.add(Skill.PICKPOCKET);
		hashSet.add(Skill.DETECT_REMOVE_TRAP);
		hashSet.add(Skill.CREEP);
		hashSet.add(Skill.RANGEDWEAPON);
		return hashSet;
	}
	
	public void moveHook(Entity e) {
		
		Collection<Collection<Location>> tilesToDisplay = 
			Location.radialCollection(e.getLocation(), e.getInfluenceRadius());
		
		for(Collection<Location> col : tilesToDisplay)
			for(Location l : col) 
				if(World.getInstance().hasTrap(l))
					World.getInstance().getTrap(l).attemptDetect(e);
	}


	/**
	 * @return the sneakAttackList
	 */
	public LinkedHashSet<Ability> getAttackList() {
		return sneakAttackList;
	}
	
	public boolean canEquip(WeaponType type) {
		switch(type) {
			case ONE_HANDED:
			case TWO_HANDED:
			case BRAWLING:
			case STAFF: return false;
			case RANGED: return true;
		}
		return false;
	}
	
	public double applySkill(Effect e) {
		return 1.0;
	}
	
	public int getRangedWeaponSkillBonus(){
		
		return (100 + rangedWeaponSkill);
	}
}
